/****************************************************************************
** ui.h extension file, included from the uic-generated form implementation.
**
** If you want to add, delete, or rename functions or slots, use
** Qt Designer to update this file, preserving your code.
**
** You should not define a constructor or destructor in this file.
** Instead, write your code in functions called init() and destroy().
** These will automatically be called by the form's constructor and
** destructor.
*****************************************************************************/
const char *dbiEntry = "databaseInterface";
const char *tableEntry="tableName";
const char *dbNEntry="databaseName";

//
// Initialize myself. Make sure that inputdata handlers take
// ownership of the pointers we will put into them.
//
void mainwindow::init()
{
   myDatabaseInterface=0;
   sForm=new settingsForm(this,"SettingsForm",TRUE);
   connect(sForm,SIGNAL(newDBParams(const QString &, const QString &, const QString &)),this,SLOT(dbiParams(const QString &, const QString &, const QString &)));

    fileMenu->setItemEnabled(fileMenu->idAt(1),FALSE);
    inputDataHandlers.setAutoDelete(TRUE);
}

// Show the widgets we have read out of our file on the screen 
// by making them children of the groupbox.
//
void mainwindow::setupWidgets()
{
    widgetData::iterator iter;
    QWidget *wP;
    
    for(iter=wData.begin();iter != wData.end(); ++iter)
    {
	wP=iter.key();
	wP->reparent(WGroupBox,wP->pos(),TRUE);
	if(isInputField(wP))
	   tabList.inSort(wP);
    }
    //    tabList.sort();
    wP=tabList.getFirst();
    if(wP)
       wP->setFocus();
    setFieldTabOrder();
}


//
// Handle fileOpen signal.
//
void mainwindow::fileOpen()
{
   widgetHandlerDictionary wHandlers;

   wHandlers.insert("defailt",new widgetHandler());
   wHandlers.insert("QLabel", new wLabelHandler());
   wHandlers.insert("QLineEdit", new wInputLineEditMaker(this,&inputDataHandlers));
   wHandlers.insert("QTextEdit", new wInputTextEditMaker(this,&inputDataHandlers));
   wHandlers.insert("QCheckBox",new wInputCheckBoxMaker(this,&inputDataHandlers));
   wHandlers.insert("QPushButton",new wInputButtonMaker(this,&inputDataHandlers));
   wHandlers.setAutoDelete(TRUE);
   currentFN=getOpenFileName();
   
   if(! currentFN.isNull())
   {
      inputDataHandlers.clear();
      ksdbFileReader myReader(currentFN,wHandlers);
      if(myReader.readFile())
      {	 
	 QSize sizeDiff=size() -WGroupBox->size();	   
	 QSize boxSize=myReader.getStartScreenSize();
	 resize(boxSize+sizeDiff);
	 WGroupBox->resize(boxSize);
	 
	 QPixmap myBG = myReader.getBGPixMap();
	 if(! myBG.isNull())
	    WGroupBox->setPaletteBackgroundPixmap(myBG);
	 wData=myReader.getData();
	 setupWidgets();
	 setupDBI();
	 fileMenu->setItemEnabled(fileMenu->idAt(1),TRUE);
      }
      else
      {
	 QMessageBox::critical(this,"Bad File",
         QString("File %1 is not valid.\nError: %2")
	.arg(currentFN).arg(myReader.errorString()));
      }
   }
   wHandlers.clear(); // Deletes all the new s above.
}
//
// Write db params to settings file.
//
void mainwindow::writeValsToSettings(QSettings *theSettings)
{
   theSettings->writeEntry(dbiEntry,currentDBI);
   theSettings->writeEntry(tableEntry,currentTableName);
   theSettings->writeEntry(dbNEntry,currentDBName);   
}
void mainwindow::setupSettingsObject(QSettings *theSettings,QString fn)
{
    theSettings->setPath("tomshiro.org","ksdb",QSettings::User);
    QFileInfo QFI(fn);
    theSettings->beginGroup(QFI.baseName(TRUE));
}

//
// Get name of model file to open (generated by modelmaker)
//
QString mainwindow::getOpenFileName()
{
    QString retVal=QFileDialog::getOpenFileName(".",
	"*.ksdb *.xml;;",
	this,
	"Open Model File",
	"Choose a Model File");
    if(! retVal.isNull())
    {
	QSettings mySettings;
	setupSettingsObject(&mySettings,retVal);
	currentDBI=mySettings.readEntry(dbiEntry);
	currentTableName=mySettings.readEntry(tableEntry);
	currentDBName=mySettings.readEntry(dbNEntry);
	if(currentDBI.isNull())
	    sForm->exec();
	if(! currentDBI.isNull())
	   writeValsToSettings(&mySettings);	   
	
    }
    if(currentDBI.isNull())
	retVal=(const char *)0;
    qDebug(
	    "currentTableName: %s currentDBI: %s currentDBName: %s",
	    (const char *)currentTableName,
	    (const char *)currentDBI, 
	    (const char *)currentDBName);   
    return retVal;   
}


//
// check Dirty flag and exit application.
//
void mainwindow::fileExit()
{
   if(screenIsDirty())
      dumpCurrentInputData();
   delete myDatabaseInterface;
    inputDataHandlers.clear(); // Delete new ed inputhandlers.
    tabList.clear();
    QApplication::exit(0);
}


void mainwindow::editUndo()
{

}


void mainwindow::editRedo()
{

}


void mainwindow::editCut()
{

}


void mainwindow::editCopy()
{

}


void mainwindow::editPaste()
{

}


void mainwindow::editFind()
{

}


void mainwindow::helpIndex()
{

}


void mainwindow::helpContents()
{

}


void mainwindow::helpAbout()
{

}

//
// Dump current contents of screen.
//
void mainwindow::dumpCurrentInputData()
{
    inputHandlerIterator iter(inputDataHandlers);
    wInputHandler *wh;
    qDebug("Dumping current input data. inputDataHandlers contains %d members",
	   inputDataHandlers.count());
    while( 0 != (wh = iter.current()))
    {
	if(! wh->isA("wButtonInputHandler"))
	    qDebug("Current contents of widget %p: %s",wh->getWidget(),(const char *)wh->getWidgetData());
	++iter;
    }
}


void mainwindow::Prev()
{
   qDebug("Prev");
   screenToDatabase();
   bool status;
   myDatabaseInterface->getPrevRecord(currentData,&status);
   if(!status)
   {
      currentData.clear();
      clearScreen();      
   }
   else
      dbFmtToScreen(currentData);

}

//
// Respond to "next" button.
//
void mainwindow::Next()
{
   qDebug("Next");
   screenToDatabase();
   bool success=TRUE;
   myDatabaseInterface->getNextRecord(currentData,&success);
   if(!success)
   {
      clearScreen();
      currentData.clear();
   }
   else
      dbFmtToScreen(currentData);    
}
void mainwindow::Search()
{
   qDebug("Search");

   currentData.clear();
   screenToDBFmt(currentData,FALSE);
   setSearchOrder();
   bool status;
   myDatabaseInterface->getRecord(currentData,&status);
   if(status)
      dbFmtToScreen(currentData);
   else
      clearScreen();

   qDebug("currentData[\"_ID\"]=%s",(const char *)currentData["_ID"]);
}


void mainwindow::First()
{   
   qDebug("First");
   screenToDatabase();
   myDatabaseInterface->getFirstRecord(currentData);
   dbFmtToScreen(currentData);
}


void mainwindow::Last()
{
   qDebug("Last");
   screenToDatabase();
   myDatabaseInterface->getLastRecord(currentData);
   dbFmtToScreen(currentData);
}

// 
// Quit button
// TODO: Provide really message if data is on screen.
//
void mainwindow::Quit()
{
   qDebug("Quit");  
   enum quitState whatAction = checkDirtyQuit();
   switch(whatAction)
   {
   case SAVE:
      screenToDatabase();
      //NO BREAK
   case QUIT:
      fileExit();
      break;
   default: // case NOQUIT
      break;
   }   
}

void mainwindow::dbiParams( const QString &tn, const QString &dn, const QString &ifn )
{
    currentTableName=tn;
    currentDBName=dn;
    currentDBI=ifn;
}
// 
// Set up database interface.
//
void mainwindow::setupDBI()
{
    colValues tableInfo;
    fieldVals theVals;
    widgetData::ConstIterator iter;

    for(iter=wData.constBegin(); iter != wData.constEnd(); ++iter)
    {
       theVals=iter.data();
       if( (theVals.contains("datatype")) && (theVals.contains("fieldname")) )
	  tableInfo[theVals["fieldname"]] = theVals["datatype"];
    }       
    if(myDatabaseInterface)
	delete myDatabaseInterface;
    
    myDatabaseInterface = new dataInterface(currentDBI,currentDBName);
    myDatabaseInterface->openDB();
    myDatabaseInterface->makeSetTable(currentTableName,tableInfo);
}

//
// Have fields on screen been edited?
//
bool mainwindow::screenIsDirty()
{
   bool retVal=FALSE;
   inputHandlerIterator iter(inputDataHandlers);
   wInputHandler *thisHandler;
   while(0 != (thisHandler =  iter.current()) )
   {
      retVal=thisHandler->hasData();
      if(retVal)
	 break;
      ++iter;
   }
   qDebug("screenIsDirty: retVal=%d",retVal);
   return retVal;
}

void mainwindow::dbFmtToScreen(const colValues &dbData)
{
   inputHandlerIterator iter(inputDataHandlers);
   wInputHandler *thisHandler;
   fieldVals widgetValues;
   while(0 != (thisHandler = iter.current()) )
   {
      QWidget *wMetaDataKey=thisHandler->getWidget();
      widgetValues=wData[wMetaDataKey];
      QString dataKey;
      if(widgetValues.contains("fieldname") )
      {
	  dataKey=widgetValues["fieldname"];
	  thisHandler->setWidgetData(dbData[dataKey]);
      }
      ++iter;
  }
 
}

//
// Dump values going to or coming from the database.
//
void mainwindow::dumpDBValues(const colValues & dv)
{
   colValues::ConstIterator iter;
   for(iter=dv.constBegin();iter != dv.constEnd();++iter)
      qDebug("Field %s value %s",(const char *)iter.key(),
	     (const char *)iter.data());

}

//
// If screen is dirty, write its contents to db.
// Called when we do prev(),next(), or first().
// NOT called for a search.
void mainwindow::screenToDatabase()
{
    if(screenIsDirty())
    {

	if(currentData.contains("_ID") )	
	{
	   screenToDBFmt(currentData,FALSE);
	   myDatabaseInterface->updateRecord(currentData);
	}
	else
	{
	   screenToDBFmt(currentData,TRUE);
	   myDatabaseInterface->appendRecord(currentData);
	}
    }
}

//
// Pull data off screen and put into database input structure.
//
void mainwindow::screenToDBFmt( colValues &outVals,bool allVals )
{
   inputHandlerIterator iter(inputDataHandlers);
   wInputHandler *thisHandler;
   fieldVals widgetValues;
   QMap<int,QString> orderFieldNames;
   
   while(0 != (thisHandler = iter.current()) )
   {
      QWidget *wMetaDataKey=thisHandler->getWidget();
      widgetValues=wData[wMetaDataKey];
      if (widgetValues.contains("fieldname"))      
      {
	 if(allVals)
	      outVals[widgetValues["fieldname"]] = 
		  thisHandler->getWidgetData();
	 if(thisHandler->hasData())
	 {
	      outVals[widgetValues["fieldname"]] = 
		  thisHandler->getWidgetData();
	      orderFieldNames[tabList.find(wMetaDataKey)]=widgetValues["fieldname"];
	  }
      }
      ++iter;
  }
   if (! orderFieldNames.isEmpty())
   {
       dbSortOrder.clear();
       //QMaps are claimed to be in sorted order.
       QMapIterator<int,QString> myIter=orderFieldNames.begin();
       while(myIter != orderFieldNames.end())       
       {
	   dbSortOrder.append(*myIter);       
	   ++myIter;
       }
   }
}

//
// Clear the Screen!
//
void mainwindow::clearScreen()
{
   inputHandlerIterator iter(inputDataHandlers);
   wInputHandler *thisHandler;
   while(0 != (thisHandler = iter.current()) )
   {
      thisHandler->clear();
      ++iter;
   }
}

void mainwindow::fileParams()
{
    qDebug("File Params");
    QString oldTN=currentTableName;
    QString oldDBN=currentDBName;
    QString oldDBI=currentDBI;

    sForm->changeValues(currentTableName,currentDBName,currentDBI);
    sForm->exec();
    if(! currentDBI.isNull())
    {
	QSettings mySettings;
	setupSettingsObject(&mySettings,currentFN);
	writeValsToSettings(&mySettings);
	setupDBI();
    }
    else
    {
       currentTableName=oldTN;
       currentDBName=oldDBN;
       currentDBI=oldDBI;
    }

}

//
// Decide if screen contains edited data, query user if necessary.
//
enum quitState mainwindow::checkDirtyQuit()
{
   enum quitState okToQuit=QUIT;
   if(screenIsDirty())
      okToQuit=SAVE;
   if(SAVE == okToQuit)
   {
      int action=QMessageBox::question(this,
      "Exit","You have unsaved changes here.",
       "Continue Editing","Save and Exit","Quit (lose changes)");
       switch(action) 
       {
       case 1:
	  okToQuit=SAVE;
	  break;
       case 2:
	  okToQuit=QUIT;
	  break;
       default:  // case 0 and safest assumption.
	  okToQuit=NOQUIT;
       }
   }
   return okToQuit;
}


void mainwindow::closeEvent( QCloseEvent * )
{
    Quit();
}


void mainwindow::setFieldTabOrder()
{
    QPtrListIterator<QWidget> iter(tabList);
    QWidget *prev=iter.current();
    QWidget *next;
    ++iter;
    while( (next=iter.current()) != 0)
    {
	setTabOrder(prev,next);
	prev=next;
	++iter;
    }
    
}


bool mainwindow::isInputField( QWidget *wP )
{
    bool retVal=FALSE;
    fieldVals fInfo=wData[wP];
    if (fInfo.contains("inputField"))
       retVal=TRUE;
    return retVal;
}

// Set the order of fields for the search. This also sets the sort order until
// overridden.
void mainwindow::setSearchOrder()
{
   QStringList::iterator it;
   for(it=dbSortOrder.begin();it != dbSortOrder.end();++it)
      qDebug("Sort Order: %s",(const char *)*it);

   myDatabaseInterface->setOrder(dbSortOrder);
}


void mainwindow::writeRecord()
{
    screenToDatabase();
    clearScreen();
}


void mainwindow::delRecord()
{
   if(currentData.contains("_ID"))
   {
      myDatabaseInterface->deleteARecord(currentData["_ID"]);
      clearScreen();
   }
   
}

//
// Set the sort order of the database back to chronological entry order
//
void mainwindow::unOrderDB()
{
    dbSortOrder.clear();
    dbSortOrder.append("_ID");
    myDatabaseInterface->setOrder(dbSortOrder);   
}
